#include <iostream>
// #include <vector>
#include <type_traits>

using std::cout;

template <typename T, int N>
struct Array_type
{
    using type = T;
    static const int dim = N;
};

template<int N>
constexpr int fac()
{
    return N*fac<N-1>();
}
template<> 
constexpr int fac<1>()
{
    return 1;
}

int main()
{
    using Array = Array_type<int, 3>;
    Array::type x{10};
    constexpr int s = Array::dim;
    std::cout << x << "\n"
              << s << "\n";
    using value_type = decltype(1.0);
    value_type y{1.9};
    std::cout << static_cast<double>(std::is_pod<int>::value) << "\n"
              << y << "\n";
    typename std::conditional<(sizeof(int)<2), int, char>::type z = 'a';
    std::cout << z << "\n";


    struct x1{
        void operator()(const int x) {cout << "x1 = " << x <<"\n";}
    };
    struct x2{
        void operator()(const int x) {cout << "x2 = " << x <<"\n";}
    };
    typename std::conditional<(9<sizeof(int)),x1, x2>::type{}(9);


    constexpr int k = fac<3>();
    cout << k <<"\n";
    return 0;
}

